﻿/*
 * ObjectLegendNode
 * 
 * initial implementation : 20.10.2008
 *
 * Copyright (c) Adam Sida, asida@centrum.cz.
 * All rights reserved.
 * 
 * for license see Petra.Gis.License.txt
 */
using System;
using System.Collections;
using System.Collections.Generic;
using Petra.Gis.Geometry;
using Petra.Gis.DataServices;
using Petra.Gis.DataServices.Metadata;
using Petra.Gis.ReferenceSystemServices.Transformations;

namespace Petra.Gis.RenderingServices.PlanarBase 
{

  /// <summary>
  /// represents legend node that can holds spatial data to display in map
  /// this node supports any <c>IEnumerable</c> data type with valid 
  /// <c>FeatureMetadata</c>.
  /// if enumerable type doesnt contain geometries directly <c>IGeometryFactory</c>
  /// might be specified to extract geometry data from
  /// </summary>
  public class ObjectLegendNode : DataLegendNodeBase
  {





    public ObjectLegendNode(LeafLegendNode parent, FeatureSetBase data, string title, RendererBase[] renderers)
      : base(parent, title)
    {
      NodeType = LegendNodeTypeEnum.DataNode;
      _data = data;

      foreach (RendererBase r in renderers)
        this.Renderers.Add(r);
    }





    public override void RenderData()
    {

      // if no renderes, then exist
      if (this.Renderers.Count == 0)
        throw new ApplicationException("no renderer available to render data");

      // prepare renderers
      // prepares also transforms in here
      // load all visual attributes (if any...)
      prepareRenders();

      // prepare spatial filter(s) for data
      // if spatialcommand refers to data with more than 1 spatial fiels
      // spatial filter must be defined for each spatial field
      if (this.Legend.Map.ApplyMapRangeAsSpatialFilter)
      {

        FeatureSpatialFilter spatialFilters = createSpatialFilter();

        // create parameter with FeatureSpatialFilter
        if (featureSet.Parameters.ContainsKey("Petra.Gis.DataServices.FeatureSpatialFilter"))
          featureSet.Parameters["Petra.Gis.DataServices.FeatureSpatialFilter"].Value = spatialFilters;

        else
        {
          FeatureSetParameter tmpParam = new FeatureSetParameter()
          {
            ParameterName = "Petra.Gis.DataServices.FeatureSpatialFilter",
            Value = spatialFilters
          };
          featureSet.Parameters.Add(tmpParam.ParameterName, tmpParam);
        }
      }

      // prepare SRSTransforms
      // put each spatial filed transform into new array item to search then
      Dictionary<string, SRSTransform> spatialFields = new Dictionary<string, SRSTransform>();
      foreach (SpatialFieldMetadata gfm in featureSet.Metadata.GeometryFieldsMetadata)
      {
        //get appropriate (non reverse) transform for each spatial field
        spatialFields.Add(gfm.Name, this.Legend.Map.SRSTransformCache.GetTransform(gfm.SRS, false));
      }

      // load data
      // step over records and paint into map...
      GeometryBase g;
      SRSTransform revTr;

      foreach (object obj in _data.Data)
      {
        foreach (KeyValuePair<string, SRSTransform> sft in spatialFields)
        {
          if (_data.GeometryConverter != null)
            g = _data.GeometryConverter.CreateGeometry(obj, sft.Key);
          else
            g = (GeometryBase)obj;

          //todo:apply spatial filter here ?
          //since IEnumerable is memory object, can always apply spatial filter

          foreach (RendererBase r in Renderers)
          {
            if (g is Grid)
            {
              if (sft.Value.IsInversible)
                revTr = sft.Value.Inverse();
              else
                revTr = this.Legend.Map.SRSTransformCache.GetTransform(sft.Value.Source, true);

              r.RenderGeometry(g);

            }
            else
              r.RenderGeometry(g);
          }
        }
      }

    }





    private FeatureSetBase _data;


    protected override IFeatureSet featureSet
    {
      get { return _data; }
      set 
      {

        validateIFeatureSet(value);

        //cast to feature set...
        _data = (FeatureSetBase)value;

        prepareRenders();
      }
    }

    
    new public FeatureSetBase FeatureSet
    {
      get { return (FeatureSetBase)featureSet; }
      set { featureSet = value; }
    }



  }
}
